﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace NMemcached.Client.Configuration
{
    /// <summary>
    /// Creates a MemcachedClient object from the nmemcached.client configuration section.
    /// </summary>
    internal static class NMemcachedConfiguration
    {
        private static readonly NMemcachedConfigurationSection ConfigSection;

        static NMemcachedConfiguration()
        {
            NMemcachedConfiguration.ConfigSection = (NMemcachedConfigurationSection)ConfigurationManager.GetSection("nmemcached.client");
        }

        /// <summary>
        /// Creates a MemcachedClient object from the nmemcached.client configuration section.
        /// </summary>
        /// <returns>A MemcachedClient object</returns>
        internal static MemcachedClient CreateClient()
        {
            if (NMemcachedConfiguration.ConfigSection == null)
            {
                throw new ConfigurationErrorsException(StringTable.Get("error_ConfigSectionNotFound"));
            }

            ServerConnectionCollection servers = new ServerConnectionCollection();

            foreach (ServerElement serverElement in NMemcachedConfiguration.ConfigSection.Servers)
            {
                ServerConnection connection = servers.AddServer(serverElement.HostOrIP, serverElement.Port, serverElement.Protocol, serverElement.Transport);

                connection.UseCompression = serverElement.UseCompression;
                connection.ReceiveTimeout = serverElement.ReceiveTimeout;
                connection.SendTimeout = serverElement.SendTimeout;

                if (serverElement.Compressor == CompressionAlgorithm.Deflate)
                {
                    connection.Compressor = new DeflateCompressor();
                }
                else
                {
                    connection.Compressor = new GZipCompressor();
                }

                switch (serverElement.PayloadEncoding)
                {
                    case EncodingType.ASCII:
                        connection.PayloadEncoding = Encoding.ASCII;
                        break;
                    case EncodingType.BigEndianUnicode:
                        connection.PayloadEncoding = Encoding.BigEndianUnicode;
                        break;
                    case EncodingType.Unicode:
                        connection.PayloadEncoding = Encoding.Unicode;
                        break;
                    case EncodingType.UTF32:
                        connection.PayloadEncoding = Encoding.UTF32;
                        break;
                    case EncodingType.UTF7:
                        connection.PayloadEncoding = Encoding.UTF7;
                        break;
                    case EncodingType.UTF8:
                    default:
                        connection.PayloadEncoding = Encoding.UTF8;
                        break;
                }

                switch (serverElement.ProtocolEncoding)
                {
                    case EncodingType.ASCII:
                        connection.ProtocolEncoding = Encoding.ASCII;
                        break;
                    case EncodingType.BigEndianUnicode:
                        connection.ProtocolEncoding = Encoding.BigEndianUnicode;
                        break;
                    case EncodingType.Unicode:
                        connection.ProtocolEncoding = Encoding.Unicode;
                        break;
                    case EncodingType.UTF32:
                        connection.ProtocolEncoding = Encoding.UTF32;
                        break;
                    case EncodingType.UTF7:
                        connection.ProtocolEncoding = Encoding.UTF7;
                        break;
                    case EncodingType.UTF8:
                    default:
                        connection.ProtocolEncoding = Encoding.UTF8;
                        break;
                }
            }

            HashAlgorithm algorithm = NMemcachedConfiguration.ConfigSection.Servers.HashAlgorithm;

            return new MemcachedClient(new ConnectionProvider(servers, algorithm));
        }
    }
}
